package Alarms;

import java.util.HashMap;
import java.util.Map.Entry;

import EventPackage.Participant;

public class AlarmController extends Participant {
	private HashMap<String, Integer> alarms = new HashMap<String , Integer>();	// Alarm set with arming/disarming times
																				// arming/disarming times:= -10: armed/disarmed [equilibrium]; 
																				// >=0: arming/disarming
																				// -1: timeout
	private int armDisarmAlarmEvtId = 7;
	private int confirmationArmDisarmEvtId = -7;	
	private int alarmLookingForControllerEvtId = 8;											
	private int confirmationAlarmRegistrationEvtId = -8;	
	private int armDisarmEvtId = 9;
	private String separator = "-@-";
	private int alarmArmDisarmFailureEvtId = 10;								
	private boolean arming = false;	
	private int armDisarmTimeOut = 100;											// Number of iterations before reporting that an alarm failed to arm/disarm 
	private int mwXpos = 0; 
	private int mwYpos = 0; 
	private int mwHeight = 198;
	private int mwWidth = 550;
	
	
	public AlarmController(String name, int subSystemHaltEnvId, String sensor_name) {
		super();
		
		this.name = name;
		
		setParameters(name, mwXpos, mwYpos, mwHeight, mwWidth, subSystemHaltEnvId, sensor_name);
	}

	@Override
	protected void initialPostPhase() {
	}

	@Override
	protected void handlePhase() {
		checkAlarmsStatus();
		
		if ( Evt.GetEventId() == alarmLookingForControllerEvtId )
		{
			String alarmId = Evt.GetMessage().split(separator)[0];

			if (! alarms.containsKey(alarmId)) {
		
				mw.WriteMessage("Registering Alarm: [" + alarmId + "]");
				alarms.put(alarmId, -10);
				postEvent(confirmationAlarmRegistrationEvtId, Evt.GetMessage());
				if (arming) armAlarm(alarmId, armDisarmTimeOut);
			}
		} // if
				
		if (Evt.GetEventId() == armDisarmEvtId )
		{
			if (Evt.GetMessage().equals("1")) {
				armAlarms();
			} else {
				disarmAlarms();
			}
		} // if
		
		if ( Evt.GetEventId() == confirmationArmDisarmEvtId )
		{
			String evtMsg = Evt.GetMessage();
			String alarmId = evtMsg.substring(0, evtMsg.length() - 1);
			char evtCommand = evtMsg.charAt(evtMsg.length() - 1);

			alarms.put(alarmId, -10);
			if (evtCommand == '1') {
				mw.WriteMessage("Arming Alarm: [" + alarmId + "] Armed");
			} else {
				mw.WriteMessage("Arming Alarm: [" + alarmId + "] Disarmed");
			}
			
		} // if
	}

	@Override
	protected void finalPostPhase() {
	}

	private void armAlarms() {
		mw.WriteMessage("Arming Alarms");
		arming = true;
		
		for (Entry<String, Integer> alarmEntry : alarms.entrySet()) {
			armAlarm(alarmEntry.getKey(), armDisarmTimeOut);
		}
	}
	
	private void disarmAlarms() {
		mw.WriteMessage("Disarming Alarms");
		arming = false;
		
		for (Entry<String, Integer> alarmEntry : alarms.entrySet()) {
			disarmAlarm(alarmEntry.getKey(), armDisarmTimeOut);
		}
	}
	
	private void armAlarm(String alarmId, int time) {
		mw.WriteMessage("Trying to arm alarm: [" + alarmId + "]");
		postEvent(armDisarmAlarmEvtId, alarmId + "1");
		alarms.put(alarmId, time);
	}
	
	private void disarmAlarm(String alarmId, int time) {
		mw.WriteMessage("Trying to disarm alarm: [" + alarmId + "]");
		postEvent(armDisarmAlarmEvtId, alarmId + "0");
		alarms.put(alarmId, time);
	}
	
	private void checkAlarmsStatus() {

		for (Entry<String, Integer> alarmEntry : alarms.entrySet()) {
			String alarmId = alarmEntry.getKey();
			int armDisarmTime = alarmEntry.getValue();
			
			if (armDisarmTime != -10) {
				armDisarmTime--;
				if (arming) {
					armAlarm(alarmId, armDisarmTime);
				} else {
					disarmAlarm(alarmId, armDisarmTime);
				}
			}
			
			if (armDisarmTime == -1) {
				if (arming) {
					mw.WriteMessage("  FAILURE:: Alarm: [" + alarmId + "] failed to arm");
					alarms.put(alarmId, -10);
					postEvent(alarmArmDisarmFailureEvtId, alarmId + "1");
				} else {
					mw.WriteMessage("  FAILURE:: Alarm: [" + alarmId + "] failed to disarm");
					alarms.put(alarmId, -10);
					postEvent(alarmArmDisarmFailureEvtId, alarmId + "0");
				}
			}
			
			
		}
	}

	@Override
	protected void customHalt() {
		// TODO Auto-generated method stub
		
	}

	@Override
	protected void beforeLooping() {
		// TODO Auto-generated method stub
		
	}
}
